using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Dyn.News.Models;
using Dyn.News.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Data;

namespace Dyn.News.Handlers {
    [UsedImplicitly]
    public class CategoryPartArchiveHandler : ContentHandler {
        public CategoryPartArchiveHandler(IRepository<CategoryPartArchiveRecord> categoryArchiveRepository, IArticleService ArticleService) {
            OnPublished<ArticlePart>((context, bp) => RecalculateCategoryArchive(categoryArchiveRepository, ArticleService, bp));
            OnUnpublished<ArticlePart>((context, bp) => RecalculateCategoryArchive(categoryArchiveRepository, ArticleService, bp));
            OnRemoved<ArticlePart>((context, bp) => RecalculateCategoryArchive(categoryArchiveRepository, ArticleService, bp));
        }

        private static void RecalculateCategoryArchive(IRepository<CategoryPartArchiveRecord> CategoryArchiveRepository, IArticleService ArticleService, ArticlePart articlePart) {
            CategoryArchiveRepository.Flush();

            // remove all current category archive records
            var CategoryArchiveRecords =
                from bar in CategoryArchiveRepository.Table
                where bar.CategoryPart == articlePart.CategoryPart.Record
                select bar;
            CategoryArchiveRecords.ToList().ForEach(CategoryArchiveRepository.Delete);

            // get all category posts for the current category
            var posts = ArticleService.Get(articlePart.CategoryPart, VersionOptions.Published);

            // create a dictionary of all the year/month combinations and their count of posts that are published in this category
            var inMemoryCategoryArchives = new Dictionary<DateTime, int>(posts.Count());
            foreach (var post in posts) {
                if (!post.Has<CommonPart>())
                    continue;

                var commonPart = post.As<CommonPart>();
                var key = new DateTime(commonPart.PublishedUtc.Value.Year, commonPart.PublishedUtc.Value.Month, 1);

                if (inMemoryCategoryArchives.ContainsKey(key))
                    inMemoryCategoryArchives[key]++;
                else
                    inMemoryCategoryArchives[key] = 1;
            }

            // create the new category archive records based on the in memory values
            foreach (KeyValuePair<DateTime, int> item in inMemoryCategoryArchives) {
                CategoryArchiveRepository.Create(new CategoryPartArchiveRecord { CategoryPart = articlePart.CategoryPart.Record, Year = item.Key.Year, Month = item.Key.Month, PostCount = item.Value });
            }
        }
    }
}